<template>
  <!--  -->
  <!-- 管理员功能：设置-用户文件页面 -->
  <!--  -->
    <div>
        <div class="top">
            <div class="top-op">

                <!-- 搜索框  @keyup.enter: 回车时执行方法 -->
                <div class="search-panel">
                    <el-input clearable placeholder="请输入文件名搜索" v-model="fileNameFuzzy" @keyup.enter="search">
                        <template #suffix>
                            <i class="iconfont icon-search" @click="search"></i>
                        </template>
                    </el-input>
                </div>
                <!-- 搜索框后面的刷新按钮 -->
                <div class="iconfont icon-refresh" @click="loadDataList"></div>

                <el-button type="danger" :disabled="selectFileIdList.length == 0" @click="delFileBatch" :style="{'margin-left':'10px'}">
                    <span class="iconfont icon-del"></span>
                    批量删除
                </el-button>
            </div>

            <!-- 自定义组件：导航 -->
            <Navigation ref="navigationRef" @navChange="navChange" :adminShow="true"></Navigation>
        </div>

        <!-- 自定义组件：文件预览 -->
        <Preview ref="previewRef"></Preview>

        <!-- tableData有数据时，遍历列表 -->
        <div class="file-list" v-if="tableData.list && tableData.list.length > 0">
            <!-- 自定义组件：列表展示
                     :dataSource：传递列表参数 
                     :fetch:      传递方法
                     @rowSelected：回调方法 -->
            <Table
              ref="dataTableRef"
              :columns="columns"
              :dataSource="tableData"
              :fetch="loadDataList"
              :initFetch="false"
              :options="tableOptions"
              @rowSelected="rowSelected"> 
                <!-- #fileName 与 186行定义的columns.scopedSlots绑定 -->
                <template #fileName="{ index, row }">
                    <!-- @mouseenter：鼠标悬停时，  @mouseleave：鼠标离开时 -->
                    <div class="file-item" @mouseenter="showOp(row)" @mouseleave="cancelShowOp(row)">

                      <!-- 展示预览封面 -->
                      <!-- 判断该项是否为视频或者图片，并转码成功 -->
                      <template v-if="(row.fileType == 1 || row.fileType == 3) && row.status == 2">
                        <!-- 传递封面给子组件 Icon.vue -->
                        <Icon :cover="row.fileCover" :width="55"></Icon>
                      </template>                    
                      <!-- 如果该项不是视频或图片，则 -->
                      <template v-else>
                        <!-- 判断为文件，则传递文件的类型给子组件，并匹配封面 -->
                        <Icon v-if="row.folderType == 0" :fileType="row.fileType"></Icon>
                        <!-- 判断为目录，则传递参数0给子组件 -->
                        <Icon v-if="row.folderType == 1" :fileType="0"></Icon>
                      </template>

                      <!-- 展示文件名 -->
                      <span class="file-name" v-if="!row.showEdit" :title="row.fileName">
                        <span @click="preview(row)">{{ row.fileName }}</span>
                        <span v-if="row.status == 0" class="transfer-status">转码中</span>
                        <span v-if="row.status == 1" class="transfer-status transfer-fail">转码失败</span>
                      </span>

                      <!-- 新建目录/重命名 时的编辑行 -->
                      <!-- 如果采用 v-show，该dom会被编译，只是根据row.showEdit隐藏与否的区别 -->
                      <!-- 会导致新建文件、重命名方法中的 editNameRef.value.focus 无法锁定是哪行 -->
                      <div class="edit-panel" v-if="row.showEdit">
                        <el-input 
                          v-model.trim="row.fileNameReal"
                          ref="editNameRef"
                          :maxlength="190"
                          @keyup.enter="saveNameEdit(index)">
                          <template #suffix>{{ row.fileSuffix }}</template>
                        </el-input>
                          <!-- saveNameEdit(index)，参数为57行，索引 -->
                        <span :class="['iconfont icon-right1', row.fileNameReal ? '' : 'not-allow']" @click="saveNameEdit(index)"></span>
                        <span class="iconfont icon-error" @click="cancelNameEdit(index)"></span>
                      </div>

                      <!-- 注意：v-show 跟 v-if 的区别 -->
                      <!-- 鼠标悬停时展示 -->
                      <span class="op">
                        <template v-if="row.showOp && row.fileId && row.status == 2">
                            <span class="iconfont icon-download" v-if="row.folderType == 0" @click="download(row)">下载</span>
                            <span class="iconfont icon-del" @click="delFile(row)">删除</span>
                        </template>
                      </span>

                    </div>
                </template>

                <!-- 展示文件大小 -->
                <template #fileSize="{ index, row }">
                    <span v-if="row.fileSize">{{ proxy.Utils.size2Str(row.fileSize) }}</span>
                </template>
            </Table>
        </div>
    </div>
</template>

<script setup>
import { ref, reactive, getCurrentInstance, nextTick, onMounted, computed } from "vue";
const { proxy } = getCurrentInstance();

//请求定义
const api = {
    loadDataList: "/admin/loadFileList",          //获取所有的文件列表
    delFile: "/admin/delFile",                    //删除文件（从数据库中删除）
    createDownloadUrl: "/admin/createDownloadUrl",//创建下载
    download: "/api/admin/download"               //文件下载                 
}; 

const columns = [
    {
        label: "文件名",
        prop: "fileName",
        scopedSlots: "fileName",
    },
    {
        label: "发布人",
        prop: "nickName",
        width: "250",
    },
    {
        label: "修改时间",
        prop: "lastUpdateTime",
        width: 200
    },
    {
        label: "大小",
        prop: "fileSize",
        scopedSlots: "fileSize",
        width: 200,
    },
]

const tableData = ref({});        //分页查询数据集
const tableOptions = ref({
    extHeight: 50,
    selectType: "checkbox",
});


const showLoading = ref(true);             //是否开启 等待响应时的样式
const currentFolder = ref({fileId: "0"});  //用于记录当前所在路径(0代表根目录)
const fileNameFuzzy = ref();               //搜索框绑定


/**
 * 搜索
 */
const search = () => {
    showLoading.value = true;
    loadDataList();
};


/**
 * 请求列表
 */
const loadDataList = async () => {
    let params = {
        pageNo: 1,
        pageSize: 10,
        fileNameFuzzy: fileNameFuzzy.value,    //文件名
        filePid: currentFolder.value.fileId,   //文件父id
    };

    //发送请求
    let result = await proxy.Request({
        url: api.loadDataList, //获取数据列表
        showLoading: showLoading.value,
        params: params,
        dataType: 'json',      //以json形式发送参数（默认是以文件形式）如不设置dataType，则后端无需使用@RequestBody接收对象
    });

    if (!result) {
        return;
    };
    tableData.value = result.data.fileList;
};


const selectFileIdList = ref([]);    //被选中的行列
//多选 由子组件Table.vue的handelSelectionChange方法调用
const rowSelected = (rows) => {
    selectFileIdList.value = [];
    rows.forEach((item) => {
        selectFileIdList.value.push(item.userId + "_" + item.fileId);   //添加
    });
};


//鼠标悬停时，展示操作按钮
const showOp = (row) => {
    //遍历数据集，给每项赋于属性showOp，用于控制操作按钮
    tableData.value.list.forEach((element) => {
        element.showOp = false;
    });
    row.showOp = true;    //当前项为被鼠标选中，展示操作按钮
};


//鼠标离开时，隐藏操作按钮
const cancelShowOp = (row) => {
    row.showOp = false;
};


/**
 * 文件下载按钮
 */
const download = async (row) => {
    let result = await proxy.Request({
        url: api.createDownloadUrl + "/" + row.userId + "/" + row.fileId,    //获取code
    });
    if (!result) {
        return;
    }
    window.location.href = api.download + "/" + result.data.downloadDto.downloadCode;  //下载
};


/**
 * 批量删除按钮
 * */
const delFileBatch = () => {
    if (selectFileIdList.value.length == 0) {
        return;
    }
    proxy.Confirm("是否确定批量删除？删除后无法还原", async () => {
        let result = await proxy.Request({
            url: api.delFile,
            params: { userIdAndFileIds: selectFileIdList.value.join(","), }, //将数组中所有的元素合并为一个字符串，元素之间通过指定字符进行分隔
        });
        if (!result) {
            return;
        };
        loadDataList();   //重新请求列表
    })
};


/**
 * 操作项中的单个删除按钮
 * */
const delFile = (row) => {
    proxy.Confirm(`是否确定删除【${row.fileName}】？删除后无法还原`, async () => {
        let result = await proxy.Request({
            url: api.delFile,
            params: { userIdAndFileIds: row.userId + "_" + row.fileId }, 
        });
        if (!result) {
            return;
        };
        loadDataList();   //重新请求列表
    })
};


/** 
 * 点击文件
*/
const navigationRef = ref();
const previewRef = ref();
const preview = (data) => {
    fileNameFuzzy.value = ref();     //清空搜索框
    //点击的是文件夹，则进入目录内
    if (data.folderType == 1) {
        navigationRef.value.openFolder(data);
        return;
    }
    //上一条if不成立，则为文件。判断文件是否转码成功
    if (data.status != 2) {
        proxy.Message.warning("文件未完成转码，无法预览");
        return
    }
    previewRef.value.showPreview(data, 1);  //文件预览。 参数：文件，类型（0：普通用户、1：管理员、2：文件分享）
};


//所在目录（导航）改变回调，由子组件 Navigation.vue 的 doCallback方法调用
const navChange = (data) => {
    const {curFolder} = data;
    currentFolder.value = curFolder;      //更新当前所在目录
    fileNameFuzzy.value = ref();          //清空搜索框
    showLoading.value = true;
    loadDataList();
};

</script>
<style lang="scss" scoped>
@import "@/assets/file.list.scss";
.search-panel {
    margin-left: 0px !important;
}
.file-list {
    margin-top: 10px;
    .file-item {
        .op {
            width: 110px;
        }
    }
}
</style>